package com.qianxin.ids.idam.am.authn.factors.cass.upsso.refreshToken;

import java.util.Comparator;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.PriorityBlockingQueue;

/**
 * @author xiongjianlin
 */
public class ConcurrentUniquePriorityQueue {
    private final PriorityBlockingQueue<RefreshEntity> queue = new PriorityBlockingQueue<>(
            300 , Comparator.comparingLong(RefreshEntity::getExpireTime));
    private final ConcurrentHashMap<String, Boolean> presenceMap = new ConcurrentHashMap<>();

    /**
     * 如果存在已有的数据，则不添加。
     * @param element
     * @return
     */
    public boolean offer(RefreshEntity element) {
        if (presenceMap.putIfAbsent(element.getContextId(), Boolean.TRUE) == null) {
            return queue.offer(element);
        }
        return false;
    }

    public RefreshEntity poll() {
        RefreshEntity element = queue.poll();
        if (element != null) {
            presenceMap.remove(element.getContextId());
        }
        return element;
    }


    public RefreshEntity peek() {
        if (queue.isEmpty()) {
            return null;
        }
        // 获取队列头部快照（避免后续并发修改影响）
        RefreshEntity entity = queue.peek();
        // 防御性校验（确保元素仍存在于映射表）
        if (entity != null && presenceMap.containsKey(entity.getContextId())) {
            return entity;
        }

        // 当检测到不一致时自动修复
        return findValidHead();
    }
    /**
     * 处理队列头元素与映射表不一致的情况（自愈逻辑）
     */
    private RefreshEntity findValidHead() {
        RefreshEntity candidate;
        while ((candidate = queue.peek()) != null) {
            if (presenceMap.containsKey(candidate.getContextId())) {
                return candidate;
            }
            // 移除已失效的队列头元素
            queue.poll();
        }
        return null;
    }
    /**
     * 线程安全移除指定元素
     * @param element 要移除的元素
     * @return 是否成功移除
     */
    public boolean remove(RefreshEntity element) {
        // 原子性操作：先移除队列中的元素
        boolean removedFromQueue = queue.remove(element);
        if (removedFromQueue) {
            // 只有当队列移除成功时，才移除映射表中的记录
            presenceMap.remove(element.getContextId());
            return true;
        }
        return false;
    }


    public int size() {
        return queue.size();
    }

    public boolean isEmpty(){
        return queue.isEmpty();
    }
}
